import { makeMap } from '@/utils/index'
import { h } from 'vue'
import { v4 as uuidv4 } from "uuid";
import { deepClone } from "@/utils/index";
// 参考https://github.com/vuejs/vue/blob/v2.6.10/src/platforms/web/server/util.js
const isAttr = makeMap(
  'accept,accept-charset,accesskey,action,align,alt,async,autocomplete,'
  + 'autofocus,autoplay,autosave,bgcolor,border,buffered,challenge,charset,'
  + 'checked,cite,class,code,codebase,color,cols,colspan,content,http-equiv,'
  + 'name,contenteditable,contextmenu,controls,coords,data,datetime,default,'
  + 'defer,dir,dirname,disabled,download,draggable,dropzone,enctype,method,for,'
  + 'form,formaction,headers,height,hidden,high,href,hreflang,http-equiv,'
  + 'icon,id,ismap,itemprop,keytype,kind,label,lang,language,list,loop,low,'
  + 'manifest,max,maxlength,media,method,GET,POST,min,multiple,email,file,'
  + 'muted,name,novalidate,open,optimum,pattern,ping,placeholder,poster,'
  + 'preload,radiogroup,readonly,rel,required,reversed,rows,rowspan,sandbox,'
  + 'scope,scoped,seamless,selected,shape,size,type,text,password,sizes,span,'
  + 'spellcheck,src,srcdoc,srclang,srcset,start,step,style,summary,tabindex,'
  + 'target,title,type,usemap,value,width,wrap'
)

function vModel(self, dataObject, defaultValue) {
  dataObject.props.value = defaultValue

  dataObject.on.input = val => {
    self.$emit('input', val)
  }
}

function emitEvents(confClone) {
  ['on', 'nativeOn'].forEach(attr => {
    const eventKeyList = Object.keys(confClone[attr] || {})
    eventKeyList.forEach(key => {
      const val = confClone[attr][key]
      if (typeof val === 'string') {
        confClone[attr][key] = event => this.$emit(val, event)
      }
    })
  })
}
function catchData(confClone) {
  const {
    tableDataType, url, method, requestBody, dataPath
  } = confClone
  // TODO: 表格布局，测试数据
  // getEditTableList().then(data => {
  //   console.log('~~~~~~~~~~~~~~~', data);
  //   if (data instanceof Array) {
  //     this.$emit('input', data)
  //   } else {
  //     this.$message.error('数据非Array')
  //   }
  // })
  // TODO: 下方根据自己封装的接口获取数据
  // if (tableDataType === 'dynamic' && url && method) {
  //   if (isValidUrl(url)) {
  //     const queryObj = {
  //       method,
  //       url
  //     }
  //     if (method === 'post') {
  //       queryObj.headers = {
  //         'Content-Type': 'application/json'
  //       }
  //       queryObj.data = requestBody
  //     }
  //      // 表格布局，测试数据
  //       getEditTableList().then(data => {
  //         console.log('~~~~~~~~~~~~~~~', data);
  //         if (data instanceof Array) {
  //           this.$emit('input', data)
  //         } else {
  //           this.$message.error('数据非Array')
  //         }
  //       })
  //     // 到底用什么发请求取决于你自己的需求
  //     this.$axios(queryObj).then(res => {
  //       // console.log('~~~~~~~~data', res);
  //       // 这里做下兼容
  //       if (dataPath) {
  //         dataPath.split('.').forEach(path => {
  //           data = data[path]
  //         })
  //       }
  //       // 更新数据
  //       if (data instanceof Array) {
  //         this.$emit('input', data)
  //       } else {
  //         this.$message.error('数据非Array')
  //       }
  //     })
  //   }
  // }
  ///////////////////end//////////////////////////////
}

function catchDirectData(confClone) {
  const {
    directs
  } = confClone

  if (!directs) return
  directs.forEach(direct => {
    // 静态数据转换
    if (direct.type === 'static') {
      try {
        // 截取数据
        const text = direct.data.substring(1, direct.data.length - 1)
        direct.arrData = JSON.parse(text)
      } catch (error) {
        direct.arrData = []
      }
    } else if (direct.type === 'dynamic' && direct.method && direct.url) { // 动态数据转换
      if (isValidUrl(direct.url)) {
        const queryObj = {
          method: direct.method,
          url: direct.url
        }
        if (direct.method === 'post') {
          queryObj.headers = {
            'Content-Type': 'application/json'
          }
          queryObj.data = direct.requestBody
        }
        // 到底用什么发请求取决于你自己的需求
        this.$axios(queryObj).then(({ data }) => {
          // 更新数据
          try {
            if (direct.map) {
              direct.arrData = eval(`(${direct.map})(data)`)
            } else {
              direct.arrData = data
            }
          } catch (error) {
            this.$message.error('数据解析失败')
          }
        })
      }
    } else {
      this.$message.error('请检查请求参数是否完整')
    }
  })
}

function isValidUrl(url) {
  try {
    const tmp = new URL(url)
    return true
  } catch (error) {
    return false
  }
}

function  createdColumnDOm (config, tableConf){
    return <el-table-column property={config.prop} label={config.label} align={tableConf.align}  show-overflow-tooltip={config.isTooltip}></el-table-column>
}

const componentChild = {
  'el-button': {
    default(h, conf, key) {
      return conf[key]
    },
  },
  'el-input': {
    prepend(h, conf, key) {
      return <template slot="prepend">{conf[key]}</template>
    },
    append(h, conf, key) {
      return <template slot="append">{conf[key]}</template>
    }
  },
  'el-select': {
    options(h, conf, key) {
      const list = []
      conf.options.forEach(item => {
        list.push(<el-option label={item.label} value={item.value} disabled={item.disabled}></el-option>)
      })
      return list
    }
  },
  'el-radio-group': {
    options(h, conf, key) {
      const list = []
      conf.options.forEach(item => {
        if (conf.optionType === 'button') list.push(<el-radio-button label={item.value}>{item.label}</el-radio-button>)
        else list.push(<el-radio label={item.value} border={conf.border}>{item.label}</el-radio>)
      })
      return list
    }
  },
  'el-checkbox-group': {
    options(h, conf, key) {
      const list = []
      conf.options.forEach(item => {
        if (conf.optionType === 'button') {
          list.push(<el-checkbox-button label={item.value}>{item.label}</el-checkbox-button>)
        } else {
          list.push(<el-checkbox label={item.value} border={conf.border}>{item.label}</el-checkbox>)
        }
      })
      return list
    }
  },
  'el-upload': {
    'list-type': (h, conf, key) => {
      const list = []
      if (conf['list-type'] === 'picture-card') {
        list.push(<i class="el-icon-plus"></i>)
      } else {
        list.push(<el-button size="small" type="primary" icon="el-icon-upload">{conf.buttonText}</el-button>)
      }
      if (conf.showTip) {
        list.push(<div slot="tip" class="el-upload__tip">只能上传不超过 {conf.fileSize}{conf.sizeUnit} 的{conf.accept}文件</div>)
      }
      return list
    }
  },
  'el-table': {
    default(h, conf, key) {
      let list = [];
      if (conf['columns']) {
        for (let i = 0; i < conf['columns'].length; i++) {
          const item = conf['columns'][i];
          let dom = createdColumnDOm(item, conf);
          list.push(dom);
        }
      }
      return list
    },
  },
  'table-cell': {
    default(h, conf, key) {
      return conf[key]
    },
  },
}

function makeDataObject() {
  // 深入数据对象：
  // https://cn.vuejs.org/v2/guide/render-function.html#%E6%B7%B1%E5%85%A5%E6%95%B0%E6%8D%AE%E5%AF%B9%E8%B1%A1
  return {
    class: {},
    attrs: {},
    props: {},
    domProps: {},
    nativeOn: {},
    on: {},
    style: {},
    directives: [],
    scopedSlots: {},
    slot: null,
    key: null,
    ref: null,
    refInFor: true
  }
}

// 在顶部导入文本组件
import TextWidget from '@/components/customer/TextWidget.vue';
import TitleWidget from '@/components/customer/TitleWidget.vue';
import EditTable from '@/components/customer/EditTable.vue'
import PhotoWall from '@/components/customer/PhotoWall.vue'
// import { getEditTableList } from '@/api/index'
export default {
  props: ['conf'],
  components: {
    EditTable,
    PhotoWall
  },
  mounted() {
    if (this.conf.tag === "EditTable") {
      // 动态请求数据
      catchData.call(this, this.conf)
      // 获取字典数据
      catchDirectData.call(this, this.conf)
    }
  },
  render(h) {
    const dataObject = makeDataObject()
    const confClone = deepClone(this.conf)
    // 如果slots文件夹存在与当前tag同名的文件，则执行文件中的代码
    const children = []
    const childObjs = componentChild[confClone.tag]
    if (childObjs) {
      Object.keys(childObjs).forEach(key => {
        const childFunc = childObjs[key]
        if (confClone[key]) {
          children.push(childFunc(h, confClone, key))
        }
      })
    }
    // 将json表单配置转化为vue render可以识别的 “数据对象（dataObject）”
    Object.keys(confClone).forEach(key => {
      const val = confClone[key]
      if (key === 'vModel') {
        vModel(this, dataObject, confClone.defaultValue)
      } else if (dataObject[key] !== undefined) {
        if (dataObject[key] === null
          || dataObject[key] instanceof RegExp
          || ['boolean', 'string', 'number', 'function'].includes(typeof dataObject[key])) {
          dataObject[key] = val
        } else if (Array.isArray(dataObject[key])) {
          dataObject[key] = [...dataObject[key], ...val]
        } else {
          dataObject[key] = { ...dataObject[key], ...val }
        }
      } else {
        dataObject.attrs[key] = val
      }
    })
    if (this.conf.tag === 'el-text') {
      return h(TextWidget, {
        props: {
          content: this.conf.content,
          styles: this.conf.style
        }
      });
    }

    if (this.conf.tag === 'el-title') {
      return h(TitleWidget, {
        props: {
          content: this.conf.content,
          tagLevel: this.conf.tagLevel,
          styles: this.conf.style
        }
      });
    }
    // 将字符串类型的事件，发送为消息
    emitEvents.call(this, confClone)

    // 将json表单配置转化为vue render可以识别的 “数据对象（dataObject）”
    // buildDataObject.call(this, confClone, dataObject)

    return h(this.conf.tag, dataObject, children)
  },
}
